package com.GB26875_3_2011.codec;

import com.GB26875_3_2011.common.CommandType;
import com.GB26875_3_2011.common.DataUnitType;
import com.GB26875_3_2011.common.GB26875Constant;
import com.GB26875_3_2011.model.GB26875Message;
import com.GB26875_3_2011.util.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author 蒋仕国
 * @projectName GB26875_3_211
 * @ClassName MessageDecoder
 * @date 2025-01-13 09:04
 * @Description: TODO [1. 消息内容解码器]
 */
@Slf4j
public class MessageDecoder extends ByteToMessageDecoder {
    /**
     * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
     * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input
     * {@link ByteBuf}.
     * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
     * @param in the {@link ByteBuf} from which to read data
     * @param out the {@link List} to which decoded messages should be added
     * @throws Exception is thrown if an error occurs
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 1. 校验最小长度
        if (in.readableBytes() < GB26875Constant.MESSAGE_HEADER_LENGTH) {
            return;
        }
        // 已经处理掉了前缀后缀
        String messageHex = ByteBufUtil.hexDump(in);
        //打印一下发送的消息
        log.info("<<<<< ip: {}, hex: {}", ctx.channel().remoteAddress(), messageHex);
        // 获取校验码
        String cCode = messageHex.substring(messageHex.length() - 2);
        // 计算校验码
        String substring = messageHex.substring(0, messageHex.length() - 2);
        if (!calculateCheckSum(substring).equalsIgnoreCase(cCode)) {
            // 校验码验证失败
            log.error("校验码验证失败, ip: {}, hex: {}", ctx.channel().remoteAddress(), messageHex);
            in.clear();
            return;
        }
        GB26875Message message = decode(in);
        // 添加到out中
        if (message != null) {
            out.add(message);
        }
    }

    private static String calculateCheckSum(String hex) {
        byte[] bytes = ByteUtils.hexStr2Bytes(hex);
        int sum = 0;
        for (byte b : bytes) {
            sum += b;
        }
        return Integer.toHexString(sum & 0xff);
    }

    private GB26875Message decode(ByteBuf in) {
        try {

            // 解析消息头部
            GB26875Message gb26875Message = new GB26875Message().setStartFlagHex(GB26875Constant.MESSAGE_START_FLAG_HEX)
                    .setEndFlagHex(GB26875Constant.MESSAGE_END_FLAG_HEX);
            // 2.1 业务流水号
            short flowId = in.readShortLE();
            // 2.2 版本号
            String versionHex = ByteUtils.readSomeByteToHex(2, in);
            gb26875Message.setFlowId(flowId).setVersionHex(versionHex);
            // 2.3 时间标志的数据
            String timeFlagHex = ByteUtils.readSomeByteToHex(6, in);
            gb26875Message.setTimeFlag(parseHexTime(timeFlagHex, GB26875Constant.BASE_YEARS));
            // 2.4 源地址
            String sourceAddressHex = ByteUtils.readSomeByteToHex(6, in);
            // 2.5 目的地址
            String destinationAddressHex = ByteUtils.readSomeByteToHex(6, in);
            gb26875Message.setSourceAddressHex(sourceAddressHex).setDestinationAddressHex(destinationAddressHex);
            // 2.6 消息体长度
            short bodyLength = in.readShortLE();
            int commId = in.readByte();
            gb26875Message.setBodyLength(bodyLength).setCommandType(CommandType.getByCode(commId));
            // 2.7读取消息体内容
            if (bodyLength > 0) {
                // 读取数据单元类型
                int dataUnitType = in.readByte();
                // 数据单元数目
                int unitCount = in.readByte();
                gb26875Message.setDataUnitType(DataUnitType.getByCode(dataUnitType)).setUnitCount(unitCount);
                byte[] bytes = ByteUtils.readSomeByte(bodyLength - 2, in);
                gb26875Message.setMessageBody(bytes);
            }
            // 2.7 校验码
            gb26875Message.setCheckCode(in.readByte());
            return gb26875Message;
        } catch (Exception e) {
            log.error("decode error", e);
            return null;
        }
    }


    public static LocalDateTime parseHexTime(String hexTime, int baseYear) {
        if (hexTime == null || hexTime.length() != 12) {
            throw new RuntimeException("Invalid hex time format, should be 12 characters long.");
        }
        // 解析各个部分
        String ss = hexTime.substring(0, 2);
        String mm = hexTime.substring(2, 4);
        String HH = hexTime.substring(4, 6);
        String dd = hexTime.substring(6, 8);
        String MM = hexTime.substring(8, 10);
        String yy = hexTime.substring(10, 12);

        // 将十六进制字符串转换为整数
        int seconds = Integer.parseInt(ss, 16);
        int minutes = Integer.parseInt(mm, 16);
        int hours = Integer.parseInt(HH, 16);
        int day = Integer.parseInt(dd, 16);
        int month = Integer.parseInt(MM, 16); // 月份从0开始
        int year = baseYear + Integer.parseInt(yy, 16); // 假设年份基准为2000年
        return LocalDateTime.of(year, month, day, hours, minutes, seconds);
    }

    @Override
    protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        super.decodeLast(ctx, in, out);
    }
}
